package de.zainodis.kitchengnome.domainmodel.persistence;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.j256.ormlite.dao.BaseDaoImpl;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.DatabaseTableConfig;
import com.j256.ormlite.table.TableUtils;

import de.zainodis.commons.LogCat;
import de.zainodis.kitchengnome.domainmodel.ItemList;
import de.zainodis.kitchengnome.domainmodel.ListItem;

/**
 * Handles persistence-related tasks for {@link ListItem}s.
 * 
 * @author fzarrai
 * 
 */
public interface IListItemDao extends Dao<ListItem, Long> {

	void saveItem(ListItem item);

	void deleteItem(ListItem item);

	/**
	 * Deletes all list items where {@link ListItem#isDone()} is true.
	 * 
	 * @param owner
	 *           the owning item list.
	 * @return the number of items that have been deleted.
	 */
	int deleteDone(ItemList owner);

	/**
	 * Deletes all list items whose owning {@link ItemList} matches the given
	 * list.
	 * 
	 * @param owner
	 *           the item list whose associated list items should be deleted.
	 * @return the number of items that have been deleted.
	 */
	int deleteItems(ItemList owner);

	/**
	 * Deletes all {@link ListItem}s.
	 * 
	 * @return the number of deleted items.
	 */
	int clearAll();

	/**
	 * @param owner
	 *           the {@link ItemList} whose items should be retrieved.
	 * @return a list of {@link ListItem} whose owner is the given list; or an
	 *         empty list if no matches were found.
	 */
	List<ListItem> getItems(ItemList owner);

	public class ListItemDao extends BaseDaoImpl<ListItem, Long> implements IListItemDao {

		private static final String TAG = "ListItemDao";

		public ListItemDao(ConnectionSource connectionSource) throws SQLException {
			super(connectionSource, ListItem.class);
		}

		public ListItemDao(ConnectionSource connectionSource, DatabaseTableConfig<ListItem> tableConfig)
				throws SQLException {
			super(connectionSource, tableConfig);
		}

		@Override
		public void saveItem(ListItem item) {
			if (item != null) {
				try {
					createOrUpdate(item);
				} catch (SQLException e) {
					LogCat.e(TAG, "Saving failed.", e);
				}
			}
		}

		public void deleteItem(ListItem item) {
			try {
				delete(item);
			} catch (SQLException e) {
				LogCat.e(TAG, "Deletion failed.", e);
			}
		}

		@Override
		public int deleteItems(ItemList owner) {
			DeleteBuilder<ListItem, Long> builder = deleteBuilder();
			int deleteCount = 0;
			try {
				builder.where().eq(ListItem.OWNING_LIST_ID_FIELD, owner.getId());
				deleteCount = delete(builder.prepare());
			} catch (SQLException e) {
				LogCat.e(TAG, "Failed to delete items of given list.", e);
			}
			return deleteCount;
		}

		@Override
		public int clearAll() {
			int deleteCount = 0;
			try {
				deleteCount = TableUtils.clearTable(connectionSource, ListItem.class);

			} catch (SQLException e) {
				LogCat.e(TAG, "Failed to clear list.", e);
			}
			return deleteCount;

		}

		@Override
		public List<ListItem> getItems(ItemList owner) {
			List<ListItem> result = null;

			QueryBuilder<ListItem, Long> builder = queryBuilder();
			try {
				builder.where().eq(ListItem.OWNING_LIST_ID_FIELD, owner.getId());
				result = query(builder.prepare());
			} catch (SQLException e) {
				LogCat.e(TAG, "Failed to obtain items of given list.", e);
			}
			if (result == null) {
				result = new ArrayList<ListItem>();
			}
			return result;

		}

		@Override
		public int deleteDone(ItemList owner) {
			DeleteBuilder<ListItem, Long> builder = deleteBuilder();
			Where where = builder.where();
			int deleteCount = 0;
			try {
				where.and(where.eq(ListItem.OWNING_LIST_ID_FIELD, owner.getId()), where.eq(ListItem.IS_DONE_FIELD, true));
				deleteCount = delete(builder.prepare());
			} catch (SQLException e) {
				LogCat.e(TAG, "Failed to delete items of given list.", e);
			}
			return deleteCount;
		}
	}

}
